package cn.yunyichina.provider.clinic.listener;

import cn.yunyichina.provider.clinic.constant.CacheConstant;
import cn.yunyichina.provider.clinic.service.impl.PayServiceImpl;
import cn.yunyichina.provider.clinic.utils.DateUtils;
import cn.yunyichina.provider.framework.common.PKGenerator;
import cn.yunyichina.provider.framework.data.SpringContextHandler;
import cn.yunyichina.provider.framework.dubbo.service.BaseService;
import cn.yunyichina.provider.framework.dubbo.service.CacheService;
import cn.yunyichina.provider.iface.entity.base.OrderExceptionVo;
import cn.yunyichina.provider.iface.entity.base.OrderExtVo;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.provider.iface.entity.pay.MchData;
import cn.yunyichina.provider.iface.entity.pay.PayCode;
import cn.yunyichina.provider.iface.entity.pay.notify.UnifiedPayNotifyMessage;
import cn.yunyichina.utils.convert.JsonUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.listener.MessageListener;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 门诊支付通知业务逻辑
 * Created by Lullaby on 2017/7/25
 */
public class ClinicPayNotifyListener implements MessageListener<Integer, String> {

    private static final Logger logger = LoggerFactory.getLogger(ClinicPayNotifyListener.class);

    @Autowired
    private PayServiceImpl payService;

    public void onMessage(ConsumerRecord<Integer, String> consumerRecord) {
        logger.info("ClinicPayNotifyListener.onMessage.consumerRecord -> {}", consumerRecord.toString());

        String data = consumerRecord.value();
        logger.info("ClinicPayNotifyListener.onMessage.data -> {}", data);

        try {
            UnifiedPayNotifyMessage notifyMessage = JsonUtils.parseObject(data, UnifiedPayNotifyMessage.class);

            String orderNo = notifyMessage.getOrderNo();
            String openId = notifyMessage.getOpenId();
            String appId = notifyMessage.getAppId();
            String transactionId = notifyMessage.getTradeNo();
            MchData attach = notifyMessage.getMchData();
            BigDecimal payAmount = new BigDecimal(notifyMessage.getPayAmount());

            Map<String, String> map = new HashMap<>();
            map.put("order_no", orderNo);
            logger.info("门诊支付回调, 订单号" + orderNo + ", 调base模块, 查询订单信息入参request=" + JSONObject.toJSONString(map));

            Response ordResponse = BaseService.callUnderlineFromInternal("yyt.base.order.by.order.no.out.get", JsonUtils.toJsonString(map));
            logger.info("门诊支付回调, 订单号" + orderNo + ", 调base模块, 查询订单信息返回response=" + JSONObject.toJSONString(ordResponse));

            if (!"0".equals(ordResponse.getResultCode())) {
                logger.info("门诊支付回调, 订单号" + orderNo + ", 调base模块, 查询订单信息失败，未找到对应的订单信息");
                throw new RuntimeException("门诊支付回调未找到订单信息");
            }

            short payMode = (short) PayCode.valueOf(attach.getPayCode()).getMode();
            OrderExtVo order = JsonUtils.parseObject(ordResponse.getResult(), OrderExtVo.class);
            order.setPaymentDealId(transactionId);
            if("1".equals(attach.getIsInsurance())){
                order.setIsInsurance((short) 1);
                order.setInsuranceMode((short)5);
            }else{
                order.setIsInsurance((short) 0);
                order.setInsuranceMode((short)0);
            }
            order.setPayMode(payMode);
            order.setPayAppId(appId);
            order.setIsPayHandled(1);//支付是否通知并处理0：否，1：是
            order.setOpenId(openId);
            order.setPayRealAmount(Double.valueOf(notifyMessage.getPayAmount()).intValue());
            if(notifyMessage.getInsuranceAmount()!=null){
                order.setInsuranceRealAmount(Double.valueOf(notifyMessage.getInsuranceAmount()).intValue());
            }
            order.setTotalRealAmount(Double.valueOf(notifyMessage.getTotalAmount()).intValue());

            //解释医保结构体
            String responseContent = notifyMessage.getMedicalContent();
            if("1".equals(attach.getIsInsurance())&&StringUtils.isNotBlank(responseContent)){
                String tempStr = null;
                try {
                    // 因为支付宝传入进来的参数中含有"{、}"、"[、]"等这些字符，所以要进行替换才能进行JSON解析
                    tempStr = responseContent.replace("\"{", "{");
                    tempStr = tempStr.replace("}\"", "}");
                    tempStr = tempStr.replace("\"[", "[");
                    tempStr = tempStr.replace("]\"", "]");
                } catch (Exception e) {
                    addOrderToExceptionList(order, "平安医保支付回调, 订单号" + orderNo + ", 解析settlement或payment出现了异常！");
                    logger.error("平安医保支付回调, 订单号" + orderNo + ", 解析settlement或payment出现了异常！", e);
                    throw e;
                }
                Map<String, String> extraParamsMap = JsonUtils.parseObject(order.getExtraParams(), HashMap.class);
                extraParamsMap.put("industry_sepc_detail", tempStr);
                order.setExtraParams(JSON.toJSONString(extraParamsMap));
            }
            logger.info("门诊支付回调, 订单号" + orderNo + ", 调base模块, 更新订单信息入参request=" + JSONObject.toJSONString(order));
            BaseService.callUnderlineFromInternal("yyt.base.order.update", JsonUtils.toJsonString(order));

            Map<String, Object> dataMap = new HashMap<>();
            // 门诊支付 - 自费
            dataMap.put("yyt_order_no", orderNo);
            dataMap.put("pay_time", notifyMessage.getPayTime());
            dataMap.put("user_id", openId == null ? "undefined" : openId);
            dataMap.put("payee_app_id", appId == null ? "undefined" : appId);
            dataMap.put("pay_mode", String.valueOf(payMode));
            dataMap.put("pay_amount", payAmount.intValue());
            dataMap.put("is_from_inner", "1");

            if (payService == null) {
                payService = SpringContextHandler.getBean(PayServiceImpl.class);
            }
            Response response = payService.ackPayOrderByOrderNoOut(JsonUtils.toJsonString(dataMap), "");
            logger.info("门诊支付回调, 订单号" + orderNo + ", 调写单返回response=" + JSONObject.toJSONString(response));

            if (!"0".equals(response.getResultCode())) {

                //记录写单的异常信息
                String errMsg = response.getResultMessage();

                Map<String, String> tmpMap = new HashMap<>();
                tmpMap.put("order_no", orderNo);
                Response orderRes = BaseService.callUnderlineFromInternal("yyt.base.order.by.order.no.out.get", JsonUtils.toJsonString(tmpMap));
                logger.info("门诊支付回调, 订单号" + orderNo + ", 调base模块, 查询订单信息返回response=" + JSONObject.toJSONString(orderRes));
                if (!"0".equals(orderRes.getResultCode())) {
                    logger.info("门诊支付回调, 订单号" + orderNo + ", 调base模块, 查询订单信息失败，未找到对应的订单信息");
                }
                order = JsonUtils.parseObject(orderRes.getResult(), OrderExtVo.class);
                order.setOrderStatusException();
                logger.info("门诊支付回调, 订单号" + orderNo + ", 调base模块, 更新订单信息入参request=" + JSONObject.toJSONString(order));
                BaseService.callUnderlineFromInternal("yyt.base.order.update", JsonUtils.toJsonString(order));
                addOrderToExceptionList(order,errMsg);
            }
        } catch (Exception e) {
            logger.error("门诊支付回调报错", e);
        }

        logger.info("门诊支付回调结束");
    }

    private void addOrderToExceptionList(OrderExtVo vo,String errorMessage) {
        logger.info("添加异常单信息, 订单号" + vo.getOrderNo() + ", 订单order=" + JSON.toJSONString(vo));
        boolean isAdd = true;
        try {
            logger.info("添加异常单信息, 订单号" + vo.getOrderNo() + ", 调用base模块, 查询是否已经存在异常单入参request=" + JSON.toJSONString(vo));
            Response response = BaseService.callUnderlineFromInternal("yyt.base.order.exception.by.order.no.get",
                    JsonUtils.toJsonString(vo));
            logger.info("添加异常单信息, 订单号" + vo.getOrderNo() + ", 调用base模块, 查询是否已经存在异常单返回response=" + JSON.toJSONString(response));
            if (!"0".equals(response.getResultCode())) {
                logger.info("添加异常单信息, 订单号" + vo.getOrderNo() + ", 调用base模块, 查询异常单信息失败");
            }

            OrderExceptionVo oe = JsonUtils.parseObject(response.getResult(), OrderExceptionVo.class);
            if (oe != null) {
                isAdd = false;
            }
        } catch (Exception e) {
            logger.info("添加异常单信息, 订单号" + vo.getOrderNo() + ", 查询异常单是否存在报错。");
        }

        if (isAdd) {
            OrderExceptionVo record = new OrderExceptionVo();
            record.setBranchCode(vo.getBranchCode());
            record.setBranchId(vo.getBranchId());
            record.setBranchName(vo.getBranchName());
            record.setCreatedTime(DateUtils.dateToString(new Date()));
            record.setExceptionHandlerCount(0);
            record.setRefundHandlerCount(0);
            record.setId(PKGenerator.generateId());
            record.setIsInsurance(vo.getIsInsurance());
            record.setOrderNo(vo.getOrderNo());
            record.setOrderType(vo.getOrderType());
            record.setOrgCode(vo.getOrgCode());
            record.setOrgId(vo.getOrgId());
            record.setOrgName(vo.getOrgName());
            record.setPlatformCode(vo.getPlatformCode());
            record.setPlatformId(vo.getPlatformId());
            record.setPlatformName(vo.getPlatformName());
            record.setPlatformOrgAppCode(vo.getPlatformOrgAppCode());
            record.setUpdateTime(DateUtils.dateToString(new Date()));
            record.setHandlerResult((short) 0);
            record.setHisQueryState((short) 0);
            record.setInsuranceHandlerFlag((short) 0);
            record.setSelfPayHandlerFlag((short) 0);

            //记录写单的异常信息
            record.setExceptionReason(errorMessage);
            record.setExceptionClass("Clinic-ClinicPayNotifyListener");

            logger.info("添加异常单信息, 订单号" + vo.getOrderNo() + ", 调用base模块, 添加异常单record=" + JSON.toJSONString(record));
            CacheService.setGlobalKey(CacheConstant.CACHE_CLINIC_MODULE, CacheConstant.CACHE_CLINIC_PAY_EXCEPTION_ORDER,
                    record.getOrderNo(), JSON.toJSONString(record), CacheConstant.CACHE_NOT_EXPIRETIME);

            BaseService.callUnderlineFromInternal("", "yyt.base.order.exception.add", JsonUtils.toJsonString(record));
        }
        logger.info("添加异常单信息, 订单号" + vo.getOrderNo() + ", 结束");
    }

}
